<template>
  <div class="contain-div">
    <!-- // 背景图放在div里 -->
    <el-image
      class="content-img"
      :src="require('@/assets/images/board-bg.png')"
      fit="fit"
    />
    <div class="chess-wrap">
      <Chess
        v-for="(item, index) in chessArr"
        :key="JSON.stringify(item) + index"
        :chessObj="item"
        :isBlank="!item"
        :showCircle="chessStatus[index].showCircle || false"
        :isUp="chessStatus[index].isUp || false"
        @onChange="flag => change(index, flag)"
      />
    </div>
    <transition
      @before-enter="beforeEnter"
      @enter="enter"
      @before-leave="beforeLeave"
      @leave="leave"
    >
      <Chess
        class="tx"
        v-if="movedTX"
        :chessObj="effectChess"
        :isBlank="false"
        :disAble="true"
      />
    </transition>
  </div>
</template>

<script>
import Chess from '@/components/Chess.vue';
import * as velocity from 'velocity-animate';
import {clickBoard} from '@/api/index.js';
const ROW_MAX = 9;
const LINE_MAX = 8;
const indexToArr = index => [Math.floor(index / ROW_MAX), index % ROW_MAX];
const arrToIndex = point => point[0] * ROW_MAX + point[1];
const getRealPos = (pos, side) => (side === 0 ? [ROW_MAX - pos[0], LINE_MAX - pos[1]] : pos);
let audio = [];
let audioIndex = 0;
const playAudio = src => {
  audio[audioIndex].src = src;
  audio[audioIndex].play();
  audioIndex = (audioIndex + 1) % audio.length;
};
export default {
  name: 'Board',
  components: {Chess},
  created() {
    audio = [new Audio(), new Audio(), new Audio(), new Audio(), new Audio()];
    this.$socket.emit('recovery', {roomId: this.$cookies.get('room').roomId});
    let arr = [];
    for (let i = 0; i < (1 + ROW_MAX) * (1 + LINE_MAX); i++) {
      arr = arr.concat({isUp: false, showCircle: false});
    }
    this.chessStatus = arr;
    this.mySide = this.$cookies.get('room').side;
  },
  data() {
    return {
      mySide: 0, // 红黑方信息
      selected: null, // 选中的棋子index
      myOrder: 0, // 是否轮到我行棋
      allowArr: [[1, 1]], // 允许的行棋位置
      chessArr: [], // 棋子二维数组
      chessStatus: [], // 棋子状态(前端)
      movedTX: false, // 移动特效标志
      start: [], // 移动特效起始位置
      finish: [], // 移动特效结束位置
      effectChess: {} // 特效(移动棋子)数据
    };
  },
  beforeDestroy() {
    audio = null;
  },
  methods: {
    hidCircle() {
      const temp = this.chessStatus.map(e => ({isUp: e.isUp, showCircle: false}));
      this.chessStatus = temp;
    },
    showCircle() {
      const [x, y] = getRealPos(indexToArr(this.selected), this.mySide);
      clickBoard({
        x,
        y,
        roomId: this.$cookies.get('room').roomId,
        control: this.myOrder
      }).then(res => {
        this.hidCircle();
        this.allowArr = [];
        if (res && res.data && res.data.length > 0) {
          this.allowArr = res.data.map(e => getRealPos(e, this.mySide));
          this.allowArr.forEach(point => {
            this.chessStatus[arrToIndex(point)].showCircle = true;
          });
        }
      }).catch(() => {
        this.$message({message: '很遗憾 获取行棋位置失败', type: 'warning'});
      });
    },
    checkMove(index) {
      let moved = false;
      if (this.selected) {
        const beginPos = indexToArr(this.selected);
        const endPos = indexToArr(index);
        if (
          Boolean(~this.allowArr.findIndex(e => e.toString() === endPos.toString()))
            && this.chessArr[this.selected].side === this.mySide
            && this.myOrder
        ) {
          this.start = beginPos;
          this.finish = endPos;
          this.effectChess = this.chessArr[this.selected];
          this.movedTX = true;
          this.$set(this.chessArr, this.selected, null);
          setTimeout(() => {
            this.movedTX = false;
            setTimeout(() => {
              this.$set(this.chessArr, index, this.effectChess);
              this.$emit('nextPlayer', getRealPos(this.finish, this.mySide));
            }, 300);
          }, 100);
          this.myOrder = 1 - this.myOrder;
          moved = true;
        }
        this.hidCircle();
        this.chessStatus[this.selected].isUp = false;
      }
      return moved;
    },
    change(index, f) {
      if (this.chessArr[index]) {
        this.chessUp(index); // 控制棋子状态
      }
      const [x, y] = indexToArr(index);
      const commonParams = {
        x,
        y,
        control: this.myOrder,
        roomId: this.$cookies.get('room').roomId
      };
      if (f === -1) {
        // 选择空白位置
        if (this.checkMove(index)) {
          this.selected = null;
        }
        else {
          clickBoard(commonParams).then(() => {
            this.selected = null;
          });
        }
      }
      else if (f === 0 && this.selected && (this.selected !== index)) {
        // 选中一个棋子后选择另外一个棋子，手动取消第一个棋子的选中状态
        if (!this.checkMove(index)) { // 行棋失败
          clickBoard(commonParams).then(() => { // 先告诉服务我点哪了
            this.selected = index; // 选择棋子变为另外一个棋子
            this.showCircle(); // 再询问服务器这个棋子的结果集
          }).catch(() => {
            this.$message({message: '诶呀 放下棋子失败了 请点击空白位置吧', type: 'warning'});
          });
        }
        else { // 行棋成功 之后点击的消息会通过complete发送
          this.hidCircle();
          this.selected = null;
          this.chessStatus[index].isUp = false;
        }
      }
      else if (f === 0) {
        // 选中一个棋子后未选择另外一个棋子，判断行棋是否合法，手动取消圆点以及选中状态
        this.checkMove(index);
        this.selected = index;
        this.showCircle();
      }
      else {
        // 放下棋子，自动取消当前棋子的选中状态并手动取消圆点
        clickBoard(commonParams).then(() => {
          this.hidCircle();
          this.selected = null;
        }).catch(() => {
          this.$message({message: '诶呀 放下棋子失败了 请点击空白位置吧', type: 'warning'});
        });
      }
    },
    chessUp(index) {
      const oldVal = this.chessStatus[index].isUp;
      this.chessStatus[index].isUp = !oldVal;
      playAudio(oldVal ? this.$audioList[0] : this.$audioList[3]); // 如果不对就调整一下顺序
    },
    beforeEnter: function (el) { // 出现位置-参数出现位置
      velocity(el, {
        left: (80 * this.start[1] + 'px'),
        top: (80 * this.start[0] + 'px'),
        opacity: 0
      }, {duration: 40});
    },
    enter(el, done) { // 从哪哪哪
      velocity(el, {opacity: 1}, {duration: 40});
      done();
    },
    beforeLeave(el) { // 移动到哪哪哪-参数结束位置
      velocity(el, {
        left: (80 * this.finish[1] + 'px'),
        top: (80 * this.finish[0] + 'px'),
        opacity: 1
      }, {duration: 180});
    },
    leave: function (el, done) { // 消失
      velocity(el, {opacity: 0}, {duration: 20});
      done();
    }
  },
  sockets: {
    gameStart(data) {
      this.$message({
        showClose: true,
        message: '游戏开始',
        type: 'success'
      });
      this.myOrder = data['p' + this.mySide];
      const res = data.board[+this.mySide];
      this.chessArr = this.mySide === 0 ? res.reverse() : res;
    },
    complete(data) {
      this.myOrder = data['p' + this.mySide];
      if (this.myOrder) {
        this.$message({
          showClose: true,
          message: '可以行棋啦!'
        });
        this.$emit('timer', true);
      }
      else {
        this.$message({
          showClose: true,
          message: '等待对手行棋'
        });
        this.$emit('timer', false);
      }
    },
    effects(data) {
      // 技能激活特效
    },
    moveTo(data) {
      let state = 0;
      if ('status' in data) {
        state = data.status;
      }
      playAudio(this.$audioList[state]);
      if (this.mySide === 0) {
        this.start = [ROW_MAX - data.start[0], LINE_MAX - data.start[1]];
        this.finish = [ROW_MAX - data.finish[0], LINE_MAX - data.finish[1]];
      }
      else {
        this.start = data.start;
        this.finish = data.finish;
      }
      this.$emit('record', { // 向上层组件提交信息并更新历史记录
        start: this.start,
        finish: this.finish,
        name: data.name,
        side: 1 - Number(data.side)
      });
      if (this.mySide === data.side) {
        const startChess = arrToIndex(this.start);
        const finishChess = arrToIndex(this.finish);
        this.effectChess = this.chessArr[startChess];
        this.movedTX = true;
        this.$set(this.chessArr, startChess, null);
        setTimeout(() => {
          this.movedTX = false;
          setTimeout(() => {
            this.$set(this.chessArr, finishChess, this.effectChess);
          }, 300);
        }, 100);
      }
    },
    updateGame(data) {
      if (this.selected != null) { // 如果我更新前拿了棋子要先取消选择
        this.allowArr = [];
        const [x, y] = indexToArr(this.selected);
        clickBoard({
          control: 1,
          x,
          y,
          roomId: this.$cookies.get('room').roomId
        }).then(() => {
          this.hidCircle();
          this.selected = null;
          this.chessStatus[this.selected] = false;
        }).catch(() => {
          this.$message({message: '诶呀 放下棋子失败了 请点击空白位置吧', type: 'warning'});
        });
      }
      const s = +this.$cookies.get('room').side;
      this.myOrder = data['p' + s];
      const chessNew = data.board[s];
      this.chessArr = this.mySide === 0 ? chessNew.reverse() : chessNew;
    }
  }
};
</script>

<style scoped>
.contain-div {
  width: max-content;
  position: relative;
}
.el-col {
  width: 81px;
}
.el-row {
  margin-bottom: 10px;
}
.content-img {
  width: 720px;
  height: 800px;
  position: absolute;
  left: 0;
  z-index: -1;
}
.chess-wrapper {
  min-height: 800px;
}
.tx {
  z-index: 10;
  opacity: 1;
  position: absolute !important;
}
.chess-wrap {
  margin: auto;
  width: 720px;
  display: grid;
  row-gap: 10px;
  grid-auto-flow: row;
  align-content: space-between;
  justify-content: space-between;
  grid-template-columns: repeat(auto-fill, 80px);
}
</style>
